package com.uminho.service;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.GregorianCalendar;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.DatePickerDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnKeyListener;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.markupartist.android.widget.ActionBar;
import com.markupartist.android.widget.ActionBar.Action;
import com.uminho.egendme.R;
import com.uminho.exceptions.InvalidOAuthParametersError;
import com.uminho.exceptions.InvalidOAuthTokenError;
import com.uminho.exceptions.OAuthServiceFailureError;
import com.uminho.exceptions.RecurrentAppointmentsException;
import com.uminho.exceptions.userOverlappedAppointmentsException;
import com.uminho.http.Webservice;
import com.uminho.objects.Resource;
import com.uminho.objects.Service;
import com.uminho.objects.Slot;
import com.uminho.objects.Task;
import com.uminho.tools.Disponibilidades;

public class ServiceDay extends Activity {
	boolean overlapAppointment=false, forcevalidcreation=false;
	EditText editTextDate = null;
	Slot slotToAppoint = null;
	long appointmentID = -1;
	Service servico = null;
	// long serviceID=-1;
	Handler messages = null;
	ArrayList<Slot> slots = null;
	GregorianCalendar day;
	ListView lister = null;
	ProgressDialog myProgressDialog = null;
	Dialog shooseTaskResource = null;
	Button ok=null;
	int EndYear=0;
	int EndMonth=0;
	int EndDay=0;
	static final int DATE_DIALOG_ID = 0;
	Spinner spinnerResource, spinnerTask;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.service_day);

		ActionBar actionBar = (ActionBar) findViewById(R.id.actionbar);
		actionBar.setHomeAction(new Action() {

			public void performAction(View view) {
				ServiceDay.this.setResult(4);
				ServiceDay.this.finish();
			}

			public int getDrawable() {
				return R.drawable.icon1;
			}
		});
		actionBar.setTitle(R.string.service_slots);

		initHandler();

		// set service id
		Bundle b = getIntent().getExtras();
		long syear = b.getLong("servicoyear", -1);
		long smonth = b.getLong("servicomonth", -1);
		long sday = b.getLong("servicoday", -1);
		servico = (Service) getIntent().getExtras().get("service");
		day = new GregorianCalendar();
		day.set(Calendar.DAY_OF_MONTH, (int) sday);
		day.set(Calendar.MONTH, (int) smonth);
		day.set(Calendar.YEAR, (int) syear);

		if (day == null) {
			day = new GregorianCalendar();
		}
		getSlots();
	}

	private void initHandler() {
		messages = new Handler() {
			@Override
			public void handleMessage(Message msg) {
				Log.d("Service Day", "what " + msg.what);
				if (msg.what == -1) {
					Toast.makeText(ServiceDay.this,
							getString(R.string.impossiblereachtheserver), 3000)
							.show();
				} else if (msg.what == -2) {
					Toast.makeText(ServiceDay.this,
							getString(R.string.impossible_assign), 3000).show();
				}else if (msg.what == -3) {
					Toast.makeText(ServiceDay.this,
							getString(R.string.emptyfields), 3000).show();
				}else if (msg.what == -4) {
					/*
					 * Overlap
					 */
					AlertDialog.Builder builder = new AlertDialog.Builder(ServiceDay.this);
					builder.setTitle(R.string.overlapproblem);
					builder.setMessage(getString(R.string.overlapquestion))
					       .setCancelable(false)
					       .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
					           public void onClick(DialogInterface dialog, int id) {
					              overlapAppointment=true;
					              //messages.sendEmptyMessage(30);
					              addAppointment();
					             
					           }
					       })
					       .setNegativeButton("No", new DialogInterface.OnClickListener() {
					           public void onClick(DialogInterface dialog, int id) {
					                dialog.cancel();
					           }
					       });
					AlertDialog alert = builder.create();
					builder.show();
				}else if (msg.what == -5) {
					/*
					 * force validate creation
					 */
					AlertDialog.Builder builder = new AlertDialog.Builder(ServiceDay.this);
					builder.setTitle(R.string.forcevalidateproblem);
					builder.setMessage(getString(R.string.forcevalidatequestion))
					       .setCancelable(false)
					       .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
					           public void onClick(DialogInterface dialog, int id) {
					              overlapAppointment=true;
					              forcevalidcreation=true;
					              addAppointment();
					             
					           }
					       })
					       .setNegativeButton("No", new DialogInterface.OnClickListener() {
					           public void onClick(DialogInterface dialog, int id) {
					                dialog.cancel();
					           }
					       });
					AlertDialog alert = builder.create();
					builder.show();
				}else if (msg.what == -6) {
					Toast.makeText(ServiceDay.this,
							getString(R.string.slotoutofbounds), 3000).show();
				}
				else if (msg.what == 30) {
					ArrayList<Resource> resources = servico.getResources();
					ArrayList<String> strRes = new ArrayList<String>();
					for (Resource r : resources) {
						strRes.add(r.getName());
					}
					ArrayList<Task> tasks = servico.getTasks();
					ArrayList<String> strTas = new ArrayList<String>();
					for (Task t : tasks) {
						strTas.add(t.getName());
					}

					shooseTaskResource = new Dialog(ServiceDay.this);
					shooseTaskResource.setTitle(R.string.addapointmenttitle);
					shooseTaskResource
							.setContentView(R.layout.choose_resource_task);
					 spinnerTask = (Spinner) shooseTaskResource
							.findViewById(R.id.task_spinner);

					// Log.d("tamanho", strTas.size()+" "+strRes.size());

					ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<String>(
							ServiceDay.this,
							android.R.layout.simple_spinner_item, strTas);
					spinnerArrayAdapter
							.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
					spinnerTask.setAdapter(spinnerArrayAdapter);

					spinnerResource = (Spinner) shooseTaskResource
							.findViewById(R.id.resource_spinner);
					ArrayAdapter<String> spinnerArrayAdapter2 = new ArrayAdapter<String>(
							ServiceDay.this,
							android.R.layout.simple_spinner_item, strRes);
					spinnerArrayAdapter2
							.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
					spinnerResource.setAdapter(spinnerArrayAdapter2);

					// buttons!!!
					 ok = (Button) shooseTaskResource
							.findViewById(R.id.buttonOK);
					Button cancel = (Button) shooseTaskResource
							.findViewById(R.id.buttonCancel);

					

					ok.setOnClickListener(new OnClickListener() {
						public void onClick(View v) {
							
							addAppointment();
						}
					});
					// cancel button
					cancel.setOnClickListener(new OnClickListener() {
						public void onClick(View v) {
							shooseTaskResource.dismiss();
						}
					});
					// advanced layout
					initAdvanced();

					shooseTaskResource.show();

				} else if (msg.what == 40) {
					// add bookmark success!
					Toast.makeText(
							ServiceDay.this,
							ServiceDay.this
									.getString(R.string.successassignappointment),
							3000).show();
					shooseTaskResource.dismiss();
					ServiceDay.this.setResult(5, ServiceDay.this.getIntent());
					ServiceDay.this.finish();

				} else {
					// connection error

				}

				if (slots == null || slots.size() <= 0) {
					showUnavailableDay();
					slots = new ArrayList<Slot>();
				}
				
				organizeAppointments(slots);
				initListView();
				if (myProgressDialog.isShowing())
					myProgressDialog.dismiss();
			}
		};
	}
	private void addAppointment(){
		final EditText editComment = (EditText) shooseTaskResource
				.findViewById(R.id.editTextComment);
		final String appointmentComent = editComment
				.getText().toString();
		myProgressDialog = ProgressDialog.show(
				ServiceDay.this,
				getString(R.string.loading),
				getString(R.string.addappointment), true);

		Thread t = new Thread() {
			public void run() {

				Webservice w = Webservice.getInstance();
				try {
					/*
					 * select choosen resource
					 */
					ArrayList<Resource> res = new ArrayList<Resource>();
					if(spinnerResource.getSelectedItemPosition()!=-1)
					res.add(servico
							.getResources()
							.get(spinnerResource
									.getSelectedItemPosition()));
					/*
					 * select choosen task
					 */
					ArrayList<Task> tas = new ArrayList<Task>();
					Log.d("sel...........", ""+spinnerTask.getSelectedItemPosition());
					if(spinnerTask.getSelectedItemPosition()!=-1)
					tas.add(servico
							.getTasks()
							.get(spinnerTask
									.getSelectedItemPosition()));
					/*
					 * set participants null
					 */
					ArrayList<String> str = new ArrayList<String>();
					str.add("");
					boolean recurrent=false;
					boolean choosedate=false;
					CheckBox checkrecurrent = (CheckBox) shooseTaskResource.findViewById(R.id.checkBoxAdvancedMode);
					if(checkrecurrent.isChecked()) recurrent=true;
					CheckBox checkdate = (CheckBox) shooseTaskResource.findViewById(R.id.checkBoxChooseDate);
					if(checkdate.isChecked()) choosedate=true;
					int delta=0;
					int times=0;
					EditText deltaET = (EditText) shooseTaskResource.findViewById(R.id.editTextDelta);
					EditText timesET = (EditText) shooseTaskResource.findViewById(R.id.editTextTimes);
					
					//testar campos
					if(recurrent){
						if(deltaET.getText().length()<=0){//erro falta o delta
								messages.sendEmptyMessage(-3);
								return;
						}
						
						if(choosedate){
							if(EndDay<=0 || EndMonth <=0 || EndYear<=0){
								messages.sendEmptyMessage(-3);
								return;
							}
						}
						else{
							if(timesET.getText().length()<=0){//erro falta times
								messages.sendEmptyMessage(-3);
								return;
							}
						}
					}
					
					/**
					 * 
					 * overlap
					 * 
					 */
					
					
					Log.d("Try to add app", "service id: "
							+ servico.getId());
					Log.d("Try to add app", "slot is null?"
							+ (slotToAppoint == null));
					Log.d("Try to add app", "start date : "
							+ slotToAppoint.getStartDate()
									.getTime()
									.toGMTString());
					Log.d("Try to add app", "end date: "
							+ slotToAppoint.getEndDate()
									.getTime()
									.toGMTString());
					if(spinnerTask.getSelectedItemPosition()!=-1)
					Log.d("Try to add app",
							"tasks: "
									+ servico
											.getTasks()
											.get(spinnerTask
													.getSelectedItemPosition())
											.getName()
											.toString());
					if(spinnerResource.getSelectedItemPosition()!=-1)
					Log.d("Try to add app",
							"resource: "
									+ servico
											.getResources()
											.get(spinnerResource
													.getSelectedItemPosition())
											.getName()
											.toString());
					Log.d("Try to add app","overlap??"+overlapAppointment);
					Log.d("Try to add app","valid creation??"+forcevalidcreation);
					
					
					if(!recurrent){
						
					/**
					 * appointment simples
					 */
						w.addAppointment(
								slotToAppoint.getStartDate(),
								appointmentComent, true, null,
								null, null, null,
								null,
								servico.getId(), res, tas, str,
								overlapAppointment, forcevalidcreation);
					}
					else{
						try{
							delta=Integer.parseInt(deltaET.getText().toString());
						}catch(Exception e){}
						
						
						if(choosedate){
						/**
						 * appoitment advanced com data de fim
						 */
							w.addAppointment(
									slotToAppoint.getStartDate(),
									appointmentComent, true, null,
									recurrent, delta, null,
									new GregorianCalendar(EndYear, EndMonth, EndDay),
									servico.getId(), res, tas, str,
									overlapAppointment, forcevalidcreation);
						}
						else{
						/**
						 * appointment advanced com times
						 */
							try{
								times=Integer.parseInt(timesET.getText().toString());
							}catch(Exception e){}
							
							w.addAppointment(
									slotToAppoint.getStartDate(),
									appointmentComent, true, null,
									recurrent, delta, times,
									null,
									servico.getId(), res, tas, str,
									overlapAppointment, forcevalidcreation);
						}
					}
					
					// refresh às disponibilidades
					Disponibilidades.serviceBusyDays = w
							.getDisponibilidadeAnual(
									(new GregorianCalendar())
											.get(GregorianCalendar.YEAR),
									servico.getId());

				} catch (InvalidOAuthTokenError e) {
					messages.sendEmptyMessage(-1);
					Log.d("Add Appointment", "token error");
					return;
				} catch (InvalidOAuthParametersError e) {
					messages.sendEmptyMessage(-1);
					Log.d("Add Appointment",
							"autentication");
					return;
				}catch (userOverlappedAppointmentsException oe) {
					messages.sendEmptyMessage(-4);
					Log.d("Add Appointment","overlap?");
					return;
				}catch (RecurrentAppointmentsException fve) {
				messages.sendEmptyMessage(-5);
				Log.d("Add Appointment","forcevalidcreation?");
				return;
			
				}catch (Exception e) {
					Log.d("Excepção", "" + e.toString());
					e.printStackTrace();
					messages.sendEmptyMessage(-2);
					overlapAppointment=false;
					forcevalidcreation=false;
					return;
				}
				messages.sendEmptyMessage(40);
				overlapAppointment=false;
				forcevalidcreation=false;
			}
		};
		t.start();
	}
	private void getSlots() {
		myProgressDialog = ProgressDialog.show(this,
				getString(R.string.loading), getString(R.string.getDayView),
				true);
		new Thread() {
			@Override
			public void run() {

				try {
					Webservice w = Webservice.getInstance();
					Log.d("getslot", "sid: " + servico.getId() + " day "
							+ day.getTime().toString());
					slots = w.getSlotByServiceByDay(servico.getId(), day);

				} catch (InvalidOAuthParametersError e) {
					messages.sendEmptyMessage(-1);
					return;
				} catch (InvalidOAuthTokenError e) {
					messages.sendEmptyMessage(-1);
					return;
				} catch (OAuthServiceFailureError e) {
					messages.sendEmptyMessage(-1);
					return;
				} catch (Exception e) {
					e.printStackTrace();
					if (slots == null || slots.size() <= 0) {
						messages.sendEmptyMessage(-2);
						return;
					}
				}
				Log.d("getslot nr: ", "" + slots.size());
				
				messages.sendEmptyMessage(1);
				

			}
		}.start();
	}
	private void showUnavailableDay(){
		//textview empty slots
		TextView emptySlots = (TextView) findViewById(R.id.textViewNoSlots);
		emptySlots.setVisibility(TextView.VISIBLE);
		//listview
		lister = (ListView) findViewById(R.id.list);
		lister.setVisibility(ListView.GONE);
		
	}
	private void initAdvanced() {
		/*
		 * button advanced
		 */
		final CheckBox advanced = (CheckBox) shooseTaskResource
				.findViewById(R.id.checkBoxAdvancedMode);
		final LinearLayout advancedLayout = (LinearLayout) shooseTaskResource
				.findViewById(R.id.linearLayoutAdvanced);

		advanced.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				if (advanced.isChecked()) {
					advancedLayout.setVisibility(LinearLayout.VISIBLE);
				} else {
					advancedLayout.setVisibility(LinearLayout.GONE);
				}
			}
		});
		/*
		 * advanced components
		 */
		final CheckBox chooseDate = (CheckBox) shooseTaskResource
				.findViewById(R.id.checkBoxChooseDate);
		final LinearLayout timesLayout = (LinearLayout) shooseTaskResource
				.findViewById(R.id.linearLayoutChooseTimes);
		final LinearLayout dateLayout = (LinearLayout) shooseTaskResource
				.findViewById(R.id.linearLayoutChooseDate);

		chooseDate.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				if (chooseDate.isChecked()) {
					timesLayout.setVisibility(LinearLayout.GONE);
					dateLayout.setVisibility(LinearLayout.VISIBLE);
				} else {
					timesLayout.setVisibility(LinearLayout.VISIBLE);
					dateLayout.setVisibility(LinearLayout.GONE);
				}
			}
		});
		/*
		 * date textbox Ao clicar na data mostra o datepiker
		 */
		editTextDate = (EditText) shooseTaskResource
				.findViewById(R.id.editTextDate);
		editTextDate.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				showDialog(DATE_DIALOG_ID);
			}
		});
	}

	private void organizeAppointments(ArrayList<Slot> sl) {

		ArrayList<Slot> aux = sl;

		Collections.sort(aux, new Comparator() {
			public int compare(Object o1, Object o2) {
				Slot p1 = (Slot) o1;
				Slot p2 = (Slot) o2;
				return p1.getStartDate().getTime()
						.compareTo(p2.getStartDate().getTime());
			}
		});
		slots = aux;

	}

	private void initListView() {
		lister = (ListView) findViewById(R.id.list);
		ItemsAdapter itemsAdapter = new ItemsAdapter(ServiceDay.this);
		lister.setAdapter(itemsAdapter);
		
	}

	private class ItemsAdapter extends BaseAdapter {

		SimpleDateFormat dateFormat;

		public ItemsAdapter(Context context) {
			dateFormat = new SimpleDateFormat("HH'h'mm'm'");
		}

		public View getView(final int position, View convertView,
				ViewGroup parent) {
			TextView mDescription;
			TextView mTitle;
			Button image;
			View view = convertView;

			if (view == null) {
				LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
				view = vi.inflate(R.layout.service_row, null);
			}
			mTitle = (TextView) view.findViewById(R.id.service_row_title);
			mTitle.setText(dateFormat.format(slots.get(position).getStartDate()
					.getTime()));

			mDescription = (TextView) view
					.findViewById(R.id.service_row_description);
			/*
			 * mDescription.setText(dateFormat.format(slots.get(position).getEndDate
			 * ().getTime()));
			 */
			 Slot s = slots.get(position);
			 final Slot auxSlot = s;
			Long appointId = s.getAppointmentId();
			Log.d("slot desc", "id " + appointId + " begin date: "
					+ s.getStartDate().getTime().toString() + " end date: "
					+ s.getEndDate().getTime().toString());
			image = (Button) view.findViewById(R.id.image);
			if (appointId == null || appointId == -1) {
				// indisponivel
				image.setCompoundDrawables(
						getResources().getDrawable(R.drawable.unavailable),
						null, null, null);
				image.setText(getResources().getString(R.string.unavailable));
				
				//image.setEnabled(false);

				mDescription.setText(getResources().getString(
						R.string.unavailable));
				mDescription.setTextColor(Color.rgb(255, 51, 51));
			} else if (appointId == 0) {
				// livre
				image.setCompoundDrawablesWithIntrinsicBounds(getResources()
						.getDrawable(R.drawable.available), null, null, null);
				image.setText(getResources().getString(R.string.assign));
				
				mDescription.setText(getResources().getString(
						R.string.available));
				mDescription.setTextColor(Color.rgb(51, 153, 51));
			} else {
				// ocupado por cliente
				image.setCompoundDrawablesWithIntrinsicBounds(getResources()
						.getDrawable(R.drawable.exchange), null, null, null);
				image.setText(getResources().getString(R.string.exchange));

				mDescription.setText(getResources().getString(R.string.busy));
				mDescription.setTextColor(Color.rgb(255, 153, 51));
			}
			image.setOnClickListener(new OnClickListener() {

				public void onClick(View v) {
					GregorianCalendar actualDate = new GregorianCalendar();
					int res = actualDate.getTime().compareTo(slots.get(position).getStartDate().getTime());
					
					if(res<=0){
						if (auxSlot.getAppointmentId() == 0) {
	
							slotToAppoint = slots.get(position);
							appointmentID = slotToAppoint.getAppointmentId();
							messages.sendEmptyMessage(30);
						} else if (auxSlot.getAppointmentId() == null
								|| auxSlot.getAppointmentId() == -1)
							messages.sendEmptyMessage(-2);
					}else messages.sendEmptyMessage(-6);
				}
			});
			return view;
		}

		public int getCount() {
			return slots.size();
		}

		public Object getItem(int position) {
			return slots.get(position);
		}

		public long getItemId(int position) {
			if (slots.get(position).getAppointmentId() != null)
				return slots.get(position).getAppointmentId();
			// else return -1;
			else
				return -1;
		}
	}

	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		Log.d("ServiceDay result", "req " + requestCode + " res " + resultCode);
	}

	@Override
	protected Dialog onCreateDialog(int id) {
		Calendar calendario = Calendar.getInstance();
		int ano = day.get(GregorianCalendar.YEAR);
		int mes = day.get(GregorianCalendar.MONTH);
		int dia = day.get(GregorianCalendar.DAY_OF_MONTH);

		switch (id) {
		case DATE_DIALOG_ID:
			Log.d("date", day.getTime().toGMTString());
			DatePickerDialog d = new DatePickerDialog(this, mDateSetListener,
					ano, mes, dia);
		

			return d;
		}
		return null;
	}

	private DatePickerDialog.OnDateSetListener mDateSetListener = new DatePickerDialog.OnDateSetListener() {
		public void onDateSet(DatePicker view, int year, int monthOfYear,
				int dayOfMonth) {
			SimpleDateFormat DF = new SimpleDateFormat("dd/MM/yyyy");
			//editTextDate.setText(dayOfMonth + "-" + monthOfYear + "-" + year);
			editTextDate.setText(DF.format((new GregorianCalendar(year, monthOfYear, dayOfMonth).getTime())));
			EndYear = year;
			EndMonth = monthOfYear;
			EndDay = dayOfMonth;
		}
	};
}
